package cn.tannn.cat.file.sdk.core.minio;

import cn.tannn.cat.file.sdk.OssOperateAPI;
import cn.tannn.cat.file.sdk.api.UploadFile;
import cn.tannn.cat.file.sdk.bean.FileIndex;
import cn.tannn.cat.file.sdk.bean.FileStorage;
import cn.tannn.cat.file.sdk.config.MinioConfig;
import cn.tannn.cat.file.sdk.constants.OSSConstants;
import cn.tannn.cat.file.sdk.exception.FileException;
import cn.tannn.cat.file.sdk.utils.AboutFileUtil;
import cn.tannn.cat.file.sdk.utils.ResponseFile;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * minio
 *
 * @author tn
 * @version 1
 * @date 2022-04-01 14:35
 */
@Service
@Slf4j
public class MinioOperate implements OssOperateAPI {

    @Override
    public FileIndex uploadFile(UploadFile upload, FileStorage storage) throws IOException {
        MinioConfig minioConfig = storage.getConfig().toJavaObject(MinioConfig.class);
        // 检查存储桶检查/创建
        MinioUtils.makeBucket(storage.getId(), upload.getBucket());
        // 内置文件名称
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String builtInNames = sdf.format(date).trim();
        // 文件名称为空值，则抛出空指针异常
        Objects.requireNonNull(upload.getFile().getOriginalFilename());
        // 文件原名称
        String originalName = upload.getFile().getOriginalFilename();
        // 文件类型后缀 如 jpg png
        String suffixDot = AboutFileUtil.getFileSuffixDot(originalName);
        // 文件上传之后的新文件名称
        String freshName;
        if (StringUtils.isNotBlank(upload.getFileName())) {
            freshName = upload.getFileName().trim() + suffixDot;
        } else {
            freshName = builtInNames + suffixDot;
        }
        String uploadPath;
        if (StringUtils.isNotBlank(upload.getChildFolder()) && !"null".equalsIgnoreCase(upload.getChildFolder())) {
            uploadPath = upload.getChildFolder() + freshName;
        } else {
            uploadPath = freshName;
        }
        try (InputStream in = upload.getFile().getInputStream()) {
            //默认类型，该“application/octet-stream”类型的时候，浏览器访问地址为下载
            String contentType = upload.getFile().getContentType();
            MinioClient minioClient = MinioUtils.getMinioClient(storage.getId());
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(upload.getBucket()).object(uploadPath).stream(
                                    in, in.available(), -1)
                            .contentType(contentType)
                            .build());
            String urlSuffix = OSSConstants.PATH_SEPARATOR + upload.getBucket() + OSSConstants.PATH_SEPARATOR + uploadPath;
            String url = minioConfig.getBrowseUrl() + urlSuffix;

            FileIndex fileStorage = new FileIndex();
            fileStorage.setStorageId(storage.getId());
            fileStorage.setStorage(storage.getStorage());
            fileStorage.setOriginalName(originalName);
            fileStorage.setFreshName(freshName);
            fileStorage.setSubPath(uploadPath);
            fileStorage.setPath(uploadPath);
            fileStorage.setUrl(url);
            fileStorage.setUrlSuffix(urlSuffix);
            fileStorage.setBucket(upload.getBucket());
            fileStorage.setBucketPath(urlSuffix);
            fileStorage.setType(upload.getFile().getContentType());
            fileStorage.setSizeUnit(AboutFileUtil.getFileSizeUnit(upload.getFile().getSize()));
            fileStorage.setSize(upload.getFile().getSize());
            return fileStorage;
        } catch (Exception e) {
            throw FileException.specialMessage("MINIO文件上传失败", e);
        }
    }


    @Override
    public boolean removeFile(FileIndex index) {
        try {
            boolean flag = MinioUtils.bucketExists(index.getStorageId(), index.getBucket());
            if (flag) {
                MinioUtils.getMinioClient(index.getStorageId()).removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(index.getBucket())
                                .object(index.getPath())
                                .build());
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("minio删除失败：index id : {} , URL: {}", index.getId(), index.getUrl(), e);
            throw FileException.specialMessage("文件删除失败");

        }
    }


    @Override
    public void downloadFile(HttpServletResponse response, FileIndex index) {
        try (InputStream in = MinioUtils.fileInputStream(index.getStorageId(), index.getBucket(), index.getPath())) {
            HttpServletResponse downResponse = ResponseFile.customResponse(response
                    , index.getType(), index.getFreshName());
            //设置文件大小
            downResponse.setHeader("Content-Length", String.valueOf(index.getSize()));
            IOUtils.copy(in, downResponse.getOutputStream());
        } catch (Exception e) {
            log.error("minio文件下载失败：index id : {} , URL: {}", index.getId(), index.getUrl(), e);
        }
    }

    @Override
    public String previewFile(FileIndex index, Integer expires) {
        try {
            return MinioUtils.getExpiryObjectUrl(index.getStorageId(), index.getBucket(), index.getPath(), expires);
        } catch (Exception e) {
            throw FileException.specialMessage("下载链接过去失败请重试", e);
        }
    }
}
